package sf.database.dialect;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sf.database.dialect.db.H2Dialect;
import sf.database.dialect.db.MariaDBDialect;
import sf.database.dialect.db.MySqlDialect;
import sf.database.dialect.db.OracleDialect;
import sf.database.dialect.db.PostgreSqlDialect;
import sf.database.dialect.db.SQLServer2005Dialect;
import sf.database.dialect.db.SQLServer2008Dialect;
import sf.database.dialect.db.SQLServer2012Dialect;
import sf.database.dialect.db.SqlServerDialect;
import sf.database.dialect.db.SqliteDialect;
import sf.database.dialect.nosql.ClickHouseDialect;
import sf.database.support.DBMS;
import sf.tools.StringUtils;

import java.util.HashMap;
import java.util.Map;

public class DialectUtils {
    private static final Logger logger = LoggerFactory.getLogger(DialectUtils.class);
    /**
     * 别名,版本号:允许动态添加方言
     */
    public static final Map<DatabaseDriver, DBDialect> DATABASE_DRIVER_DB_DIALECT_MAP = new HashMap<>();

    public final static MySqlDialect mysql = new MySqlDialect();
    public final static MariaDBDialect mariadb = new MariaDBDialect();
    public final static PostgreSqlDialect postgresql = new PostgreSqlDialect();
    public final static SqliteDialect sqlite = new SqliteDialect();
    public final static SqlServerDialect sqlserver = new SqlServerDialect();
    public final static SqlServerDialect sqlserver2005 = new SQLServer2005Dialect();
    public final static SqlServerDialect sqlserver2008 = new SQLServer2008Dialect();
    public final static SqlServerDialect sqlserver2012 = new SQLServer2012Dialect();
    public final static OracleDialect oracle = new OracleDialect();
    public final static H2Dialect h2 = new H2Dialect();
    public final static ClickHouseDialect clickhouse = new ClickHouseDialect();

    static {
        DATABASE_DRIVER_DB_DIALECT_MAP.put(DatabaseDriver.MYSQL, mysql);
        DATABASE_DRIVER_DB_DIALECT_MAP.put(DatabaseDriver.MARIADB, mariadb);

        DATABASE_DRIVER_DB_DIALECT_MAP.put(DatabaseDriver.POSTGRESQL, postgresql);

        DATABASE_DRIVER_DB_DIALECT_MAP.put(DatabaseDriver.SQLITE, sqlite);

        DATABASE_DRIVER_DB_DIALECT_MAP.put(DatabaseDriver.SQLSERVER, sqlserver);

        DATABASE_DRIVER_DB_DIALECT_MAP.put(DatabaseDriver.ORACLE, oracle);

        DATABASE_DRIVER_DB_DIALECT_MAP.put(DatabaseDriver.H2, h2);

        DATABASE_DRIVER_DB_DIALECT_MAP.put(DatabaseDriver.CLICKHOUSE, clickhouse);
    }


    /**
     * 自定义方言查找方法
     */
    public static LookDialect lookDialect;

    /**
     * 获取数据库方言
     * @param name    名称
     * @param version 版本号
     * @return
     */
    public static DBDialect getDialect(String name, String version) {
        DatabaseDriver driver = DatabaseDriver.fromProductName(name);
        DBDialect dialect = DATABASE_DRIVER_DB_DIALECT_MAP.get(driver);
        if (dialect == null) {
            if (lookDialect != null) {
                dialect = lookDialect.getDBDialect(name, version);
            }
            if (dialect == null) {
                logger.error("未找到对应的数据库方言,使用默认方言 dialect.name = " + name);
                return DefaultDBDialect.instance;
            }
        }
        //针对sqlserver的特殊处理
        if (DBMS.sqlserver.getNumber() == dialect.getNumber()) {
            if (StringUtils.isNotBlank(version)) {
                int v = Integer.parseInt(version.substring(0, version.indexOf('.')));
                if (v < 9) {
                    return dialect;
                } else if (v == 9) {
                    return sqlserver2005;
                } else if (v == 10) {
                    return sqlserver2008;
                }
                //v=11,sqlserver2012;
                //v=12,sqlserver2014;
                //v=13,sqlserver2016;
                //...
                else {
                    return sqlserver2012;
                }
            }
        }
        return dialect;
    }
}
